package com.example.tiantian.contact;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.RawContacts;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.util.Log;

class ContactHelper {
    private ContactHelper(Context context) {
        resolver = context.getContentResolver();
    }

    private static ContentResolver resolver;

    private static ContactHelper helper;

    public static ContactHelper getHelper(Context context) {
        if (helper == null) {
            helper = new ContactHelper(context);

        }
        return helper;
    }

    public long add(ContactInfo info) {
        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
        ContentProviderOperation cpo = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
                .withValue(RawContacts.DELETED, "0").build();
        operations.add(cpo);

        cpo = ContentProviderOperation.newInsert(Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
                .withValue(StructuredName.DISPLAY_NAME, info.name).build();
        operations.add(cpo);

        cpo = ContentProviderOperation.newInsert(Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE).withValue(Organization.COMPANY, info.company)
                .withValue(Organization.TITLE, info.position).build();
        operations.add(cpo);

        cpo = ContentProviderOperation.newInsert(Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE).withValue(Email.ADDRESS, info.email).build();
        operations.add(cpo);

        cpo = ContentProviderOperation.newInsert(Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE)
                .withValue(StructuredPostal.FORMATTED_ADDRESS, info.address)
                .withValue(StructuredPostal.POSTCODE, info.zipcode).build();
        operations.add(cpo);

        cpo = ContentProviderOperation.newInsert(Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE).withValue(Phone.NUMBER, info.mobilephone)
                .withValue(Phone.TYPE, Phone.TYPE_MOBILE).build();
        operations.add(cpo);

        cpo = ContentProviderOperation.newInsert(Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE).withValue(Phone.NUMBER, info.familyphone)
                .withValue(Phone.TYPE, Phone.TYPE_HOME).build();
        operations.add(cpo);

        cpo = ContentProviderOperation.newInsert(Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE).withValue(Phone.NUMBER, info.officephone)
                .withValue(Phone.TYPE, Phone.TYPE_WORK).build();
        operations.add(cpo);

        cpo = ContentProviderOperation.newInsert(Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE).withValue(Phone.NUMBER, info.othercontact)
                .withValue(Phone.TYPE, Phone.TYPE_OTHER).build();
        operations.add(cpo);

        cpo = ContentProviderOperation.newInsert(Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, Photo.CONTENT_ITEM_TYPE).withValue(Photo.PHOTO, info.photo).build();
        operations.add(cpo);

        try {

            ContentProviderResult[] cpr = resolver.applyBatch(ContactsContract.AUTHORITY, operations);
            Uri reusltUri = cpr[0].uri;
            long id = ContentUris.parseId(reusltUri);
            return id;
        } catch (RemoteException e) {
            Log.e(getClass().getName(), e.toString());
        } catch (OperationApplicationException e) {
            Log.e(getClass().getName(), e.toString());
        }
        return -1;
    }

    public long update(ContactInfo info) {
        String selection = " raw_contact_id = ? and mimetype= ? ";
        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();

        ContentProviderOperation.Builder builder = ContentProviderOperation.newUpdate(Data.CONTENT_URI)
                .withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
                .withValue(StructuredName.DISPLAY_NAME, info.name)
                .withSelection(selection, new String[] { info._id + "", StructuredName.CONTENT_ITEM_TYPE });
        operations.add(builder.build());

        builder = ContentProviderOperation.newUpdate(Data.CONTENT_URI)
                .withSelection(selection, new String[] { info._id + "", Organization.CONTENT_ITEM_TYPE })
                .withValue(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE).withValue(Organization.COMPANY, info.company)
                .withValue(Organization.TITLE, info.position);
        operations.add(builder.build());

        builder = ContentProviderOperation.newUpdate(Data.CONTENT_URI)
                .withSelection(selection, new String[] { info._id + "", Email.CONTENT_ITEM_TYPE })
                .withValue(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE).withValue(Email.ADDRESS, info.email);
        operations.add(builder.build());

        builder = ContentProviderOperation.newUpdate(Data.CONTENT_URI)
                .withSelection(selection, new String[] { info._id + "", StructuredPostal.CONTENT_ITEM_TYPE })
                .withValue(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE)
                .withValue(StructuredPostal.FORMATTED_ADDRESS, info.address)
                .withValue(StructuredPostal.POSTCODE, info.zipcode);
        operations.add(builder.build());

        builder = ContentProviderOperation.newUpdate(Data.CONTENT_URI).withValueBackReference(Data.RAW_CONTACT_ID, 0)
                .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE).withValue(Phone.NUMBER, info.mobilephone)
                .withValue(Phone.TYPE, Phone.TYPE_MOBILE);
        operations.add(builder.build());

        builder = ContentProviderOperation.newUpdate(Data.CONTENT_URI)
                .withSelection(selection, new String[] { info._id + "", Phone.CONTENT_ITEM_TYPE })
                .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE).withValue(Phone.NUMBER, info.familyphone)
                .withValue(Phone.TYPE, Phone.TYPE_HOME);
        operations.add(builder.build());

        builder = ContentProviderOperation.newUpdate(Data.CONTENT_URI)
                .withSelection(selection, new String[] { info._id + "", Phone.CONTENT_ITEM_TYPE })
                .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE).withValue(Phone.NUMBER, info.officephone)
                .withValue(Phone.TYPE, Phone.TYPE_WORK);
        operations.add(builder.build());

        builder = ContentProviderOperation.newUpdate(Data.CONTENT_URI)
                .withSelection(selection, new String[] { info._id + "", Phone.CONTENT_ITEM_TYPE })
                .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE).withValue(Phone.NUMBER, info.othercontact)
                .withValue(Phone.TYPE, Phone.TYPE_OTHER);
        operations.add(builder.build());

        builder = ContentProviderOperation.newUpdate(Data.CONTENT_URI)
                .withSelection(selection, new String[] { info._id + "", Photo.CONTENT_ITEM_TYPE })
                .withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE).withValue(Photo.PHOTO, info.photo);
        operations.add(builder.build());

        try {
            resolver.applyBatch(ContactsContract.AUTHORITY, operations);
            return info._id;
        } catch (RemoteException e) {
            Log.e(getClass().getName(), e.toString());
        } catch (OperationApplicationException e) {
            Log.e(getClass().getName(), e.toString());
        }
        return -1;
    }

    public long delete(long where) {
        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
        String selection = " = ?";

        ContentProviderOperation cpo = ContentProviderOperation.newDelete(Data.CONTENT_URI)
                .withSelection(Data.RAW_CONTACT_ID + selection, new String[] { "" + where }).build();
        operations.add(cpo);
        cpo = ContentProviderOperation.newDelete(RawContacts.CONTENT_URI)
                .withSelection(RawContacts._ID + selection, new String[] { "" + where }).build();
        operations.add(cpo);

        try {
            resolver.applyBatch(ContactsContract.AUTHORITY, operations);
            return where;
        } catch (RemoteException e) {
            Log.e(getClass().getName(), e.toString());
        } catch (OperationApplicationException e) {
            Log.e(getClass().getName(), e.toString());
        }
        return -1;
    }

    public int delete() {
        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>();
        ContentProviderOperation cpo = ContentProviderOperation.newDelete(Data.CONTENT_URI).build();
        operations.add(cpo);

        cpo = ContentProviderOperation.newDelete(RawContacts.CONTENT_URI).build();
        operations.add(cpo);

        try {
            ContentProviderResult[] cpr = resolver.applyBatch(ContactsContract.AUTHORITY, operations);
            return cpr.length;
        } catch (RemoteException e) {
            Log.e(getClass().getName(), e.toString());
        } catch (OperationApplicationException e) {
            Log.e(getClass().getName(), e.toString());
        }
        return -1;
    }

    public List<ContactInfo> query() {
        List<ContactInfo> list = new ArrayList<ContactInfo>();
        Cursor c = resolver.query(RawContacts.CONTENT_URI, new String[] { RawContacts._ID }, " deleted = 0 ", null,
                null);
        while (c.moveToNext()) {
            ContactInfo info = new ContactInfo();
            info._id = c.getInt(c.getColumnIndex(RawContacts._ID));

            Cursor cData = resolver.query(Data.CONTENT_URI, null, Data.RAW_CONTACT_ID + " = ? ",
                    new String[] { info._id + "" }, null);
            while (cData.moveToNext()) {
                String mimeType = cData.getString(cData.getColumnIndex(Data.MIMETYPE));
                if (mimeType.equals(StructuredName.CONTENT_ITEM_TYPE)) {
                    info.name = cData.getString(cData.getColumnIndex(StructuredName.DISPLAY_NAME));
                } else if (mimeType.equals(Phone.CONTENT_ITEM_TYPE)) {
                    int type = cData.getInt(cData.getColumnIndex(Phone.TYPE));
                    switch (type) {
                    case Phone.TYPE_HOME:
                        info.familyphone = cData.getString(cData.getColumnIndex(Phone.NUMBER));
                        break;
                    case Phone.TYPE_WORK:
                        info.officephone = cData.getString(cData.getColumnIndex(Phone.NUMBER));
                        break;
                    case Phone.TYPE_MOBILE:
                        info.mobilephone = cData.getString(cData.getColumnIndex(Phone.NUMBER));
                        break;
                    case Phone.TYPE_OTHER:
                        info.othercontact = cData.getString(cData.getColumnIndex(Phone.NUMBER));
                        break;
                    default:
                        break;
                    }
                } else if (mimeType.equals(StructuredPostal.CONTENT_ITEM_TYPE)) {

                    info.address = cData.getString(cData.getColumnIndex(StructuredPostal.FORMATTED_ADDRESS));
                    info.zipcode = cData.getString(cData.getColumnIndex(StructuredPostal.POSTCODE));
                } else if (mimeType.equals(Organization.CONTENT_ITEM_TYPE)) {
                    info.company = cData.getString(cData.getColumnIndex(Organization.COMPANY));
                    info.position = cData.getString(cData.getColumnIndex(Organization.TITLE));
                } else if (mimeType.equals(Email.CONTENT_ITEM_TYPE)) {
                    info.email = cData.getString(cData.getColumnIndex(Email.ADDRESS));
                } else if (mimeType.equals(Photo.CONTENT_ITEM_TYPE)) {
                    info.photo = cData.getBlob(cData.getColumnIndex(Photo.PHOTO));
                    if (info.photo != null) {
                        info.length = info.photo.length;
                    }
                }
            }
            list.add(info);
        }
        return list;
    }
}
